<?php

declare(strict_types=1);

namespace App\Services\Orders;

use App\Constants\Order\OrderCode;
use App\Exception\InvalidRequestException;
use App\Services\Goods\Good;
use App\Utils\Services\BaseServices;
use App\Model\Orders\Order as OrderModel;
use App\Services\Users\User as UserServices;
use Hyperf\Database\Model\Builder;
use Hyperf\Database\Model\ModelNotFoundException;
use Hyperf\DbConnection\Db;
use function Hyperf\Support\make;
use function Hyperf\Translation\__;

/**
 * Class Order
 * @author zx
 * @package App\Services\Orders
 */
Class Order extends BaseServices
{
    /**
     * 模型
     * @return string
     */
    public function model():string
    {
        return OrderModel::class;
    }

    /**
     * 下单
     * @param array $params
     * @return OrderModel
     */
    public function setOrder(array $params)
    {

        /** @var OrderModel $model */
        $this->setModel($this->model());
        $params['no'] = $this->getModel()->getNo();

        /** @var UserServices $userServices */
        $userServices = make(UserServices::class);
        $userModel = $userServices->register($params);
        /** @var Good $goodServices */
        $goodServices = make(Good::class);
        $goodsModel = $goodServices->whereIn('product_id', array_column($params['goods'], 'product_id'))->get();


        return Db::transaction(function () use ($userModel, $params, $goodsModel) {
            $params['user_id'] = $userModel->id;
            /** @var OrderModel $orderModel */
            if ($params['source'] === 'mini' && !$params['jump']) {
                $this->checkCustoms486($params['payer']['id_card'], $params['payer']['mobile'], $params['address']);

                $params['payer_name'] = $params['payer']['name'];
                $params['payer_no'] = $params['payer']['id_card'];
                $params['payer_mobile'] = $params['payer']['mobile'];
                $params['payer']['openid'] = $params['open_id'];
                $params['payer']['app_id'] = $params['appid'];
            }
            $orderModel = $this->create($params);
            if (!$orderModel->exists) {
                throw new InvalidRequestException();
            }
            $orderGoodsData = [];

            $goodsPluck = $goodsModel->pluck('product_id');
            foreach ($params['goods'] as $good) {
                $key = $goodsPluck->search($good['product_id']);
                if (false === $key) {
                    throw new ModelNotFoundException();
                }
                $goodData = $goodsModel->get($key);
                $goodData['goodsImg'] = $goodData['image'];
                $goodData['goodsName'] = $goodData['name'];
                $good['good'] = $goodData;
                $good['good_no'] = $goodData['no'];
                $good['product_id'] = $goodData['product_id'];
                $good['barcode'] = $goodData['barcode'];
                $orderGoodsData[] = $good;
            }

            $orderModel->goods()->createMany($orderGoodsData);

            return $orderModel;
        });
    }

    /**
     * 应海关486号文件要求,对用户购买进行限制
     * 同一订购人证件号对应多个不同订购人电话/多个不同收货人地址/多个不同收货人电话
     * 同一订购人电话对应多个不同订购人证件号/多个不同收货人地址/多个不同收货人电话
     * 同一收件人电话对应多个不同收货人地址
     * @param string $idCard
     * @param string $mobile
     * @param string $address
     * @param int $maxCount
     * @throws InvalidRequestException
     */
    public function checkCustoms486(string $idCard, string $mobile, string $address, int $maxCount=10):void
    {
        $count = $this->select(['id'])->where(function (Builder $builder) use ($idCard, $mobile, $address) {
            $builder->orWhere('payer_no', $idCard)
                ->orWhere('payer_mobile', $mobile);
        })
            ->whereIn('pay_status', [
                OrderCode::PAY_STATUS_PAID, OrderCode::PAY_STATUS_PART_PAID,
                OrderCode::PAY_STATUS_APPLY_REFUND, OrderCode::PAY_STATUS_PART_REFUND,
                OrderCode::PAY_STATUS_REFUSE_REFUND
            ])
            ->whereYear('created_at', date('Y'))
            ->whereMonth('created_at', date('m'))
            ->groupBy('payer_no', 'payer_mobile')
            ->limit(10)
            ->get()->count();
        logs("Check Customs 486: {$count}");
        if ($count >= $maxCount) {
            $exists = $this->where('payer_no', $idCard)
                ->where('payer_mobile', $mobile)
                ->whereIn('pay_status', [
                    OrderCode::PAY_STATUS_PAID, OrderCode::PAY_STATUS_PART_PAID,
                    OrderCode::PAY_STATUS_APPLY_REFUND, OrderCode::PAY_STATUS_PART_REFUND,
                    OrderCode::PAY_STATUS_REFUSE_REFUND
                ])
                ->whereYear('created_at', date('Y'))
                ->whereMonth('created_at', date('m'))
                ->exists();
            if (!$exists) {
                throw new InvalidRequestException(__('message.customs_486_limit'));
            }
        }
    }
}
